﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Zore.App.Shared.Helpers.Invoker
{
    public class FormUrlencodedInvoker : InvokerContributor
    {
        public FormUrlencodedInvoker(string baseAddress) : base(baseAddress)
        {
        }

        /// <summary>
        /// Inner Invoke With Return
        /// </summary>
        /// <typeparam name="TReturn"></typeparam>
        /// <typeparam name="TData">Data must be Dictionary<string, string></typeparam>
        /// <param name="requestUri"></param>
        /// <param name="method"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public override async Task<TReturn> InnerInvokeWithReturn<TReturn, TData>(
            string requestUri, HttpMethod method, TData data = null)
        {
            var result = default(TReturn);

            using (var client = new HttpClient())
            {
                using (var request = BuildHttpRequestMessage(requestUri, method, data))
                {
                    try
                    {
                        client.BaseAddress = BaseAddress;
                        var msg = await client.SendAsync(request);
                        if (msg.StatusCode == HttpStatusCode.OK)
                        {
                            var strResult = await msg.Content.ReadAsStringAsync();
                            result = JsonConvert.DeserializeObject<TReturn>(strResult);
                        }
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(
                            $"Error:{ex.Message} Inner Error:{ex.InnerException.Message}");
                    }
                    return result;
                }
            }
        }

        public override async Task InnerInvokeWithoutReturn<TData>(
            string requestUri, HttpMethod method, TData data = null)
        {
            using (var client = new HttpClient())
            {
                using (var request = BuildHttpRequestMessage(requestUri, method, data))
                {
                    client.BaseAddress = BaseAddress;
                    var msg = await client.SendAsync(request);
                }
            }
        }

        public override HttpRequestMessage BuildHttpRequestMessage<TData>(
            string requestUri, HttpMethod method, TData data = null)
        {
            var parameters = data as Dictionary<string, string>;

            var request = new HttpRequestMessage(method, CreateUrl(new Uri(requestUri), parameters));
            if (data != null)
            {
                var content = new StringContent(null, Encoding.UTF8);
                request.Content = content;
                request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
            }
            return request;
        }

        private static string CreateUrl(Uri endpoint, Dictionary<string, string> values)
        {
            var qs = string.Join("&", values.Select(kvp => string.Format("{0}={1}", WebUtility.UrlEncode(kvp.Key), WebUtility.UrlEncode(kvp.Value))).ToArray());
            return $"{endpoint.AbsoluteUri}?{qs}";
        }
    }
}
